/***********************************************************************************
 * 文件名： touch_key.c
 * 版本： 5
 * 说明：
 * 		触摸键控制组件，提供环境自适应、超时重置、电压波动补偿等功能，提供一个稳定可靠的触摸
 * 	键是否按下的状态。建议配合 btn_ctrl 组件进行使用，在配合使用时，本组间提供按钮是否按下的
 * 	状态供查询。
 *      在配置文件中进行配置，针对POLSYS_LITE，需要间隔10~40ms调用 TouchKey_Scan 。使用示
 * 	例请见 POLSYS 项目中的 projects\touch_key_demo .
 * 修改记录：
 * 	2021/08/20: 初版。 刘言。
 *  2021/10/15: 增加 TouchKey_SetScanStatus API；增加 _TOUCH_KEY_VOLTAGE_SENSITIVITY 配置项。
 *  2022/02/10：增加 动态灵敏度以及诸多配置项；增加 _TouchKey_PauseCondition API
 *  2022/02/21：解决开启动态灵敏度后基准值无法达到最大值的BUG，单通道时代码占用ROM优化
 *  2022/06/06: 去掉发送捕获值功能；新增 _TOUCH_KEY_USE_SET_STATUS；占用优化。刘言。
 ***********************************************************************************/
#include "touch_key.h"
#include "..\..\polsys.h"

#ifdef _TOUCH_KEY_USE_SET_STATUS
static xdata bool mRun = true;
#endif
#if (_TOUCH_KEY_CH_NUM == 1)
    bit TouchKey_mKeyStatus;                                 //按键状态标志，分别对应"CapSensor.h"中的CH0 CH1 ...
    static xdata u16 mKeyUpCont, mKeyDownCont; //各个按键按下与松手计时，可读取作为长按判断，KeyUpCont从2开始有效
    NO_INIT static xdata u16 mRefValue;                           //各个按键基准值
    #ifdef _TOUCH_DYNAMIC_SENSITIVITY
        static xdata s16 VALID_VALUE = _TOUCH_KEY_VALID_VALUE_CH0;
    #else
        #define VALID_VALUE  _TOUCH_KEY_VALID_VALUE_CH0
    #endif//有效（按下）差值
    #ifdef _TOUCH_DYNAMIC_SENSITIVITY
        static xdata s16 INVALID_VALUE = _TOUCH_KEY_INVALID_VALUE_CH0;
    #else
        #define INVALID_VALUE  _TOUCH_KEY_INVALID_VALUE_CH0
    #endif//无效（释放）差值

    #ifdef _TOUCH_DYNAMIC_SENSITIVITY
        // 动态灵敏度需要的变量
        static xdata u16 mValidMaxValue, mValidMinValue;
        static xdata u8 mValidValueTime, mIncreasedSensitivityTiming;
    #endif

    #ifdef _TOUCH_HOLD_ABNORMAL_PROTECTION
        // 异常触发保护需要的变量
        static xdata u8 mTriggerCumulativeTime, mTriggerProtectionTime;
    #endif
#else
    xdata bool TouchKey_mKeyStatus[_TOUCH_KEY_CH_NUM];                                 //按键状态标志，分别对应"CapSensor.h"中的CH0 CH1 ...
    static xdata u16 mKeyUpCont[_TOUCH_KEY_CH_NUM], mKeyDownCont[_TOUCH_KEY_CH_NUM]; //各个按键按下与松手计时，可读取作为长按判断，KeyUpCont从2开始有效
    NO_INIT static xdata u16 mRefValue[_TOUCH_KEY_CH_NUM];                           //各个按键基准值
    #ifdef _TOUCH_DYNAMIC_SENSITIVITY
        static xdata s16 VALID_VALUE[_TOUCH_KEY_CH_NUM] = {_TOUCH_KEY_VALID_VALUE_CH0
    #else
        static C51_CODE const s16 VALID_VALUE[_TOUCH_KEY_CH_NUM] = {_TOUCH_KEY_VALID_VALUE_CH0
    #endif
                                                    ,_TOUCH_KEY_VALID_VALUE_CH1
    #if (_TOUCH_KEY_CH_NUM > 2)
                                                    ,_TOUCH_KEY_VALID_VALUE_CH2
    #endif
        }; //有效（按下）差值
    #ifdef _TOUCH_DYNAMIC_SENSITIVITY
        static xdata s16 INVALID_VALUE[_TOUCH_KEY_CH_NUM] = {_TOUCH_KEY_INVALID_VALUE_CH0
    #else
        static C51_CODE const s16 INVALID_VALUE[_TOUCH_KEY_CH_NUM] = {_TOUCH_KEY_INVALID_VALUE_CH0
    #endif
                                                    ,_TOUCH_KEY_INVALID_VALUE_CH1
    #if (_TOUCH_KEY_CH_NUM > 2)
                                                    ,_TOUCH_KEY_INVALID_VALUE_CH2                   
    #endif
        }; //无效（释放）差值

    #ifdef _TOUCH_DYNAMIC_SENSITIVITY
        // 动态灵敏度需要的变量
        static xdata u16 mValidMaxValue[_TOUCH_KEY_CH_NUM], mValidMinValue[_TOUCH_KEY_CH_NUM];
        static xdata u8 mValidValueTime[_TOUCH_KEY_CH_NUM], mIncreasedSensitivityTiming[_TOUCH_KEY_CH_NUM];
    #endif

    #ifdef _TOUCH_HOLD_ABNORMAL_PROTECTION
        // 异常触发保护需要的变量
        static xdata u8 mTriggerCumulativeTime[_TOUCH_KEY_CH_NUM], mTriggerProtectionTime[_TOUCH_KEY_CH_NUM];
    #endif
#endif

#ifdef _TOUCH_KEY_USE_VOLTAGE_COMPENSATE
static bit mEnVoltageCompensate = true;
static xdata u16 mLastVDD; //上次扫描时的电压值
static void VoltageCompensate();
#endif

#ifndef POLSYS_LITE
static pdata polsys_task_t mTask;
#endif


// 参数含义：false表示不初始化基准值 true：初始化基准值
void TouchKey_Init(bool reset_ref)
{
#if (_TOUCH_KEY_CH_NUM > 1)
    u8 i;
#endif
#ifdef _TOUCH_KEY_USE_POWS
    u16 cap_value, last_value, diff_value;
    u8 j, num;
#endif
    _TouchKey_CapSSInit();
    //获取初始基准值
#if (_TOUCH_KEY_CH_NUM == 1)
        if (reset_ref)
        {
    #ifdef _TOUCH_KEY_USE_POWS
            last_value = _TouchKey_CapSSGetValue(0);
            num = 0;
            for (j = 0; j < _TOUCH_KEY_PO_MAX_WAIT_COUNT; j++)
            {
                cap_value = _TouchKey_CapSSGetValue(0);
                if (cap_value > last_value)
                    diff_value = cap_value - last_value;
                else
                    diff_value = last_value - cap_value;
                if (diff_value <= _TOUCH_KEY_PO_STABLE_VALUE)
                {
                    num++;
                    if (num >= _TOUCH_KEY_PO_STABLE_COUNT)
                    {
                        break;
                    }
                }
                else
                {
                    // 超出范围则更新旧纪录，减少累计误差
                    last_value = cap_value;
                    num = 0;
                }
            }
            mRefValue = cap_value;
    #else
            mRefValue = _TouchKey_CapSSGetValue(0);
    #endif
        }
        TouchKey_mKeyStatus = false;
    #ifdef _TOUCH_DYNAMIC_SENSITIVITY
        mValidMaxValue = mRefValue;
        mValidMinValue = mRefValue;
        mValidValueTime = 0;
        mIncreasedSensitivityTiming = 0;
    #endif
    #ifdef _TOUCH_HOLD_ABNORMAL_PROTECTION
        mTriggerCumulativeTime = 0;
        mTriggerProtectionTime = 0;
    #endif
#else
    for (i = 0; i < _TOUCH_KEY_CH_NUM; i++)
    {
        if (reset_ref)
        {
#ifdef _TOUCH_KEY_USE_POWS
            last_value = _TouchKey_CapSSGetValue(i);
            num = 0;
            for (j = 0; j < _TOUCH_KEY_PO_MAX_WAIT_COUNT; j++)
            {
                cap_value = _TouchKey_CapSSGetValue(i);
                if (cap_value > last_value)
                    diff_value = cap_value - last_value;
                else
                    diff_value = last_value - cap_value;
                if (diff_value <= _TOUCH_KEY_PO_STABLE_VALUE)
                {
                    num++;
                    if (num >= _TOUCH_KEY_PO_STABLE_COUNT)
                    {
                        break;
                    }
                }
                else
                {
                    // 超出范围则更新旧纪录，减少累计误差
                    last_value = cap_value;
                    num = 0;
                }
            }
            mRefValue[i] = cap_value;
#else
            mRefValue[i] = _TouchKey_CapSSGetValue(i);
#endif
        }
        TouchKey_mKeyStatus[i] = false;
#ifdef _TOUCH_DYNAMIC_SENSITIVITY
        mValidMaxValue[i] = mRefValue[i];
        mValidMinValue[i] = mRefValue[i];
        mValidValueTime[i] = 0;
        mIncreasedSensitivityTiming[i] = 0;
#endif
#ifdef _TOUCH_HOLD_ABNORMAL_PROTECTION
        mTriggerCumulativeTime[i] = 0;
        mTriggerProtectionTime[i] = 0;
#endif
    }
#endif
#ifdef _TOUCH_KEY_USE_VOLTAGE_COMPENSATE
    //获取初始电压值
    mLastVDD = _TouchKey_GetVDDVoltage();
#endif
#ifndef POLSYS_LITE
    Polsys_TaskInit(&mTask, TouchKey_Scan, _TOUCH_KEY_SCAN_INTERVAL);
#endif
}



#ifdef _TOUCH_KEY_USE_SET_STATUS
FORCE_IN_LINE void TouchKey_SetScanStatus(bool new_status)
{
    mRun = new_status;
}
#endif

#if (_TOUCH_KEY_CH_NUM == 1)
void TouchKey_Scan()
{
    u16 cap_value;
    s16 diff_value;

#ifdef _TOUCH_KEY_USE_SET_STATUS
    if (mRun)
#endif
    {
#ifdef _TOUCH_KEY_USE_VOLTAGE_COMPENSATE
        if (mEnVoltageCompensate)
            VoltageCompensate();
#endif
#ifdef _TouchKey_PauseCondition
            // 有条件停止部分通道采集 并释放触摸键
            if (_TouchKey_PauseCondition())
            {
                cap_value = mRefValue;
                diff_value = 0;
            }
            else
#endif
            {
                cap_value = _TouchKey_CapSSGetValue(0);
                diff_value = (s16)cap_value - (s16)mRefValue;
            }
#ifdef _TOUCH_HOLD_ABNORMAL_PROTECTION
            // 2022年1月3日：黄均铭，异常输出保护功能
            // 触发保护计时
            if (mTriggerProtectionTime < 255)
                mTriggerProtectionTime++;
#endif
            if (TouchKey_mKeyStatus) // 现在是按下状态
            {
                if (diff_value <= INVALID_VALUE) //可能松手了
                {
#if _TOUCH_KEY_UP_VALID_CNT > 1
                    mKeyUpCont++;
                    if (mKeyUpCont >= _TOUCH_KEY_UP_VALID_CNT) // 连续2次检测到松手信号
#endif
                    {
                        TouchKey_mKeyStatus = false; //标记松手了
                        mKeyDownCont = 0;
#ifdef _TOUCH_HOLD_ABNORMAL_PROTECTION
                        // 输出过程中不稳定判断 - 输出过程中释放了，如果刚刚已经稳定，则初始化不稳定判断
                        if (mTriggerProtectionTime > (_TOUCH_HOLD_PERIOD_TIME / _TOUCH_KEY_SCAN_INTERVAL))
                        {
                            mKeyUpCont = (_TOUCH_RELEASE_PERIOD_TIMEOUT / _TOUCH_KEY_SCAN_INTERVAL);
                            mTriggerProtectionTime = 0;
                            mTriggerCumulativeTime = 0;
                        }
#endif
                    }
                }
                else //按着（未松手）
                {
                    mKeyUpCont = 0;
                    mKeyDownCont++;
#ifdef _TOUCH_HOLD_ABNORMAL_PROTECTION
                    // 触发后 在设定时间内，判断是否误触发
                    if (mTriggerProtectionTime <= (_TOUCH_HOLD_PERIOD_TIME / _TOUCH_KEY_SCAN_INTERVAL))
                    {
                        mTriggerCumulativeTime++;
                        if (diff_value > VALID_VALUE)
                        {
                            mTriggerCumulativeTime++;
                        }
                    }
                    // 未满足正常触发条件 降低灵敏度，并且释放按键
                    else if (mTriggerCumulativeTime < (_TOUCH_HOLD_CUMULATIVE_TIME / _TOUCH_KEY_SCAN_INTERVAL))
                    {
                        mRefValue = cap_value;
                        TouchKey_mKeyStatus = false;
                        mKeyDownCont = 0;
                    }
#endif
                    if (mKeyDownCont == (_TOUCH_KEY_RESET_TIMEOUT / _TOUCH_KEY_SCAN_INTERVAL)) //超时重置基准值
                    {
                        mRefValue = cap_value;
                    }
                }
            }
            else // 现在是松手状态
            {
                if (diff_value >= VALID_VALUE) // 可能按下了
                {
#if _TOUCH_KEY_DOWN_VALID_CNT > 1
                    mKeyDownCont++;
                    if (mKeyDownCont >= _TOUCH_KEY_DOWN_VALID_CNT) // 连续2次检测到按下信号
#endif
                    {
                        TouchKey_mKeyStatus = true; // 标记按下了
                        mKeyUpCont = 0;
                    }
                }
                else //一直松手状态
                {
                    mKeyDownCont = 0;
                    if (mKeyUpCont < 0xFFFF)
                        mKeyUpCont++;
#ifdef _TOUCH_HOLD_ABNORMAL_PROTECTION
                    // 触发保护计时
                    if (mKeyUpCont >= (_TOUCH_RELEASE_PERIOD_TIMEOUT / _TOUCH_KEY_SCAN_INTERVAL))
                    {
                        mTriggerCumulativeTime = 0;
                        mTriggerProtectionTime = 0;
                    }
#endif
#ifdef _TOUCH_DYNAMIC_SENSITIVITY
                    // 动态灵敏度思路：
                    //   不稳定判断 1.采集最大值超出当前基础值 2.波动值计算出的阈值大于当前阈值
                    //   不稳定措施 1.基础值设为新的最大值 2.更新阈值
                    //   持续稳定措施 1.缓慢调高灵敏度
                    // 初始化最大值和最小值 - 释放后 采集固定空个数
                    if (mKeyUpCont == (_TOUCH_RELEASE_START_DETECTION / _TOUCH_KEY_SCAN_INTERVAL))
                    {
                        mValidMaxValue = cap_value;
                        mValidMinValue = cap_value;
                        mValidValueTime = 0;
                    }
                    // 记录最大值
                    if (mValidMaxValue < cap_value)
                    {
                        mValidMaxValue = cap_value;
                        mValidValueTime = 0;
                    }
                    // 记录最小值
                    if (mValidMinValue > cap_value)
                    {
                        mValidMinValue = cap_value;
                        mValidValueTime = 0;
                    }
                    // 未触发时的校准 - 已持续一段时间稳定波动，并且已记录最大值和最小值
                    mValidValueTime++;
                    if (mValidValueTime >= (_TOUCH_REF_MAX_VALUE_LATER_TIME / _TOUCH_KEY_SCAN_INTERVAL))
                    {
                        u16 fluctuating, nearby;
                        // 时间分片计数
                        mIncreasedSensitivityTiming++;
                        // 获取当前基准值变化 并更新基准值
                        if (mValidMaxValue > mRefValue)
                        {
                            nearby = 0;
                            mRefValue = mValidMaxValue; // 更新基准值
                            mIncreasedSensitivityTiming = 0;    // 变得不灵敏了，重新计数
                        }
                        else
                        {
                            nearby = mRefValue - mValidMaxValue;
                        }
                        // 获取当前波动值
                        fluctuating = mValidMaxValue - mValidMinValue;
                        // 根据基础值和波动值计算阈值
                        if (fluctuating <= _TOUCH_INITIAL_FLUCTUATION_VALUE)
                        {
                            fluctuating = _TOUCH_KEY_VALID_MIN_VALUE_CH0;
                        }
                        else
                        {
                            fluctuating = _TOUCH_KEY_VALID_MIN_VALUE_CH0 + fluctuating * _TOUCH_THRESHOLD_MULTIPLE;
                            if (fluctuating > _TOUCH_KEY_VALID_MAX_VALUE_CH0)
                                fluctuating = _TOUCH_KEY_VALID_MAX_VALUE_CH0;
                        }
                        // 判断计算阈值与当前阈值的变化
                        if (fluctuating > VALID_VALUE)
                        {
                            VALID_VALUE = fluctuating;                      // 更新阈值
                            INVALID_VALUE = (VALID_VALUE >> 1) + 1; // 更新阈值
                            mIncreasedSensitivityTiming = 0;                // 重新计数
                        }

                        // 持续一段时间灵敏度增加，谨慎调整阈值（增加灵敏度）
                        if (mIncreasedSensitivityTiming >= (_TOUCH_RELEASE_INCREASED_INTERVAL / _TOUCH_REF_MAX_VALUE_LATER_TIME))
                        {
                            mIncreasedSensitivityTiming = (_TOUCH_RELEASE_INCREASED_INTERVAL / _TOUCH_REF_MAX_VALUE_LATER_TIME);
                            // 调整阈值
                            VALID_VALUE -= _TOUCH_KEY_VALID_INCREMENT;
                            if (VALID_VALUE < fluctuating)
                                VALID_VALUE = fluctuating;
                            INVALID_VALUE = (VALID_VALUE >> 1) + 1;
                            // 调低基准值（增加灵敏度）
                            if (nearby >= 2)
                                mRefValue -= (nearby >> 1);
                            else
                                mRefValue = mValidMaxValue; // 更新基准值
                        }
                        // 初始化
                        mValidMaxValue = cap_value;
                        mValidMinValue = cap_value;
                        mValidValueTime = 0;
                    }
#else
                    if (mKeyUpCont >= (_TOUCH_KEY_RESET_REF_INTERVAL / _TOUCH_KEY_SCAN_INTERVAL)) //松手的时间达到重置基准值
                    {
                        if (diff_value >= _TOUCH_KEY_SAFE_RESET_DIFF) // 当前值在 基准值-1 以上
                        {
                            mRefValue = cap_value; // 直接作为新的基准值
                            mKeyUpCont = 0;
                        }
                        else //当前值变小，且小了很多(-2及以下)
                        {
                            if (mKeyUpCont >= (_TOUCH_KEY_RESET_TIMEOUT / _TOUCH_KEY_SCAN_INTERVAL)) //达到超时时间（无条件重置时间）
                            {
                                mRefValue = cap_value;
                                mKeyUpCont = 0;
                            }
                        }
                    }
#endif
                }
            }
    }
}
#else // #if (_TOUCH_KEY_CH_NUM == 1)
void TouchKey_Scan()
{
    u16 cap_value;
    s16 diff_value;
    u8 now_ch;

#ifdef _TOUCH_KEY_USE_SET_STATUS
    if (mRun)
#endif
    {
#ifdef _TOUCH_KEY_USE_VOLTAGE_COMPENSATE
        if (mEnVoltageCompensate)
            VoltageCompensate();
#endif
        for (now_ch = 0; now_ch < _TOUCH_KEY_CH_NUM; now_ch++) // 循环扫描每个触摸键
        {
#ifdef _TouchKey_PauseCondition
            // 有条件停止部分通道采集 并释放触摸键
            if (_TouchKey_PauseCondition())
            {
                cap_value = mRefValue[now_ch];
                diff_value = 0;
            }
            else
#endif
            {
                cap_value = _TouchKey_CapSSGetValue(now_ch);
                diff_value = (s16)cap_value - (s16)mRefValue[now_ch];
            }
#ifdef _TOUCH_HOLD_ABNORMAL_PROTECTION
            // 2022年1月3日：黄均铭，异常输出保护功能
            // 触发保护计时
            if (mTriggerProtectionTime[now_ch] < 255)
                mTriggerProtectionTime[now_ch]++;
#endif
            if (TouchKey_mKeyStatus[now_ch]) // 现在是按下状态
            {
                if (diff_value <= INVALID_VALUE[now_ch]) //可能松手了
                {
#if _TOUCH_KEY_UP_VALID_CNT > 1
                    mKeyUpCont[now_ch]++;
                    if (mKeyUpCont[now_ch] >= _TOUCH_KEY_UP_VALID_CNT) // 连续2次检测到松手信号
#endif
                    {
                        TouchKey_mKeyStatus[now_ch] = false; //标记松手了
                        mKeyDownCont[now_ch] = 0;
#ifdef _TOUCH_HOLD_ABNORMAL_PROTECTION
                        // 输出过程中不稳定判断 - 输出过程中释放了，如果刚刚已经稳定，则初始化不稳定判断
                        if (mTriggerProtectionTime[now_ch] > (_TOUCH_HOLD_PERIOD_TIME / _TOUCH_KEY_SCAN_INTERVAL))
                        {
                            mKeyUpCont[now_ch] = (_TOUCH_RELEASE_PERIOD_TIMEOUT / _TOUCH_KEY_SCAN_INTERVAL);
                            mTriggerProtectionTime[now_ch] = 0;
                            mTriggerCumulativeTime[now_ch] = 0;
                        }
#endif
                    }
                }
                else //按着（未松手）
                {
                    mKeyUpCont[now_ch] = 0;
                    mKeyDownCont[now_ch]++;
#ifdef _TOUCH_HOLD_ABNORMAL_PROTECTION
                    // 触发后 在设定时间内，判断是否误触发
                    if (mTriggerProtectionTime[now_ch] <= (_TOUCH_HOLD_PERIOD_TIME / _TOUCH_KEY_SCAN_INTERVAL))
                    {
                        mTriggerCumulativeTime[now_ch]++;
                        if (diff_value > VALID_VALUE[now_ch])
                        {
                            mTriggerCumulativeTime[now_ch]++;
                        }
                    }
                    // 未满足正常触发条件 降低灵敏度，并且释放按键
                    else if (mTriggerCumulativeTime[now_ch] < (_TOUCH_HOLD_CUMULATIVE_TIME / _TOUCH_KEY_SCAN_INTERVAL))
                    {
                        mRefValue[now_ch] = cap_value;
                        TouchKey_mKeyStatus[now_ch] = false;
                        mKeyDownCont[now_ch] = 0;
                    }
#endif
                    if (mKeyDownCont[now_ch] == (_TOUCH_KEY_RESET_TIMEOUT / _TOUCH_KEY_SCAN_INTERVAL)) //超时重置基准值
                    {
                        mRefValue[now_ch] = cap_value;
                    }
                }
            }
            else // 现在是松手状态
            {
                if (diff_value >= VALID_VALUE[now_ch]) // 可能按下了
                {
#if _TOUCH_KEY_DOWN_VALID_CNT > 1
                    mKeyDownCont[now_ch]++;
                    if (mKeyDownCont[now_ch] >= _TOUCH_KEY_DOWN_VALID_CNT) // 连续2次检测到按下信号
#endif
                    {
                        TouchKey_mKeyStatus[now_ch] = true; // 标记按下了
                        mKeyUpCont[now_ch] = 0;
                    }
                }
                else //一直松手状态
                {
                    mKeyDownCont[now_ch] = 0;
                    if (mKeyUpCont[now_ch] < 0xFFFF)
                        mKeyUpCont[now_ch]++;
#ifdef _TOUCH_HOLD_ABNORMAL_PROTECTION
                    // 触发保护计时
                    if (mKeyUpCont[now_ch] >= (_TOUCH_RELEASE_PERIOD_TIMEOUT / _TOUCH_KEY_SCAN_INTERVAL))
                    {
                        mTriggerCumulativeTime[now_ch] = 0;
                        mTriggerProtectionTime[now_ch] = 0;
                    }
#endif
#ifdef _TOUCH_DYNAMIC_SENSITIVITY
                    // 动态灵敏度思路：
                    //   不稳定判断 1.采集最大值超出当前基础值 2.波动值计算出的阈值大于当前阈值
                    //   不稳定措施 1.基础值设为新的最大值 2.更新阈值
                    //   持续稳定措施 1.缓慢调高灵敏度
                    // 初始化最大值和最小值 - 释放后 采集固定空个数
                    if (mKeyUpCont[now_ch] == (_TOUCH_RELEASE_START_DETECTION / _TOUCH_KEY_SCAN_INTERVAL))
                    {
                        mValidMaxValue[now_ch] = cap_value;
                        mValidMinValue[now_ch] = cap_value;
                        mValidValueTime[now_ch] = 0;
                    }
                    // 记录最大值
                    if (mValidMaxValue[now_ch] < cap_value)
                    {
                        mValidMaxValue[now_ch] = cap_value;
                        mValidValueTime[now_ch] = 0;
                    }
                    // 记录最小值
                    if (mValidMinValue[now_ch] > cap_value)
                    {
                        mValidMinValue[now_ch] = cap_value;
                        mValidValueTime[now_ch] = 0;
                    }
                    // 未触发时的校准 - 已持续一段时间稳定波动，并且已记录最大值和最小值
                    mValidValueTime[now_ch]++;
                    if (mValidValueTime[now_ch] >= (_TOUCH_REF_MAX_VALUE_LATER_TIME / _TOUCH_KEY_SCAN_INTERVAL))
                    {
                        u16 fluctuating, nearby;
                        // 时间分片计数
                        mIncreasedSensitivityTiming[now_ch]++;
                        // 获取当前基准值变化 并更新基准值
                        if (mValidMaxValue[now_ch] > mRefValue[now_ch])
                        {
                            nearby = 0;
                            mRefValue[now_ch] = mValidMaxValue[now_ch]; // 更新基准值
                            mIncreasedSensitivityTiming[now_ch] = 0;    // 变得不灵敏了，重新计数
                        }
                        else
                        {
                            nearby = mRefValue[now_ch] - mValidMaxValue[now_ch];
                        }
                        // 获取当前波动值
                        fluctuating = mValidMaxValue[now_ch] - mValidMinValue[now_ch];
                        // 根据基础值和波动值计算阈值
                        if (fluctuating <= _TOUCH_INITIAL_FLUCTUATION_VALUE)
                        {
                            fluctuating = _TOUCH_KEY_VALID_MIN_VALUE_CH0;
                        }
                        else
                        {
                            fluctuating = _TOUCH_KEY_VALID_MIN_VALUE_CH0 + fluctuating * _TOUCH_THRESHOLD_MULTIPLE;
                            if (fluctuating > _TOUCH_KEY_VALID_MAX_VALUE_CH0)
                                fluctuating = _TOUCH_KEY_VALID_MAX_VALUE_CH0;
                        }
                        // 判断计算阈值与当前阈值的变化
                        if (fluctuating > VALID_VALUE[now_ch])
                        {
                            VALID_VALUE[now_ch] = fluctuating;                      // 更新阈值
                            INVALID_VALUE[now_ch] = (VALID_VALUE[now_ch] >> 1) + 1; // 更新阈值
                            mIncreasedSensitivityTiming[now_ch] = 0;                // 重新计数
                        }

                        // 持续一段时间灵敏度增加，谨慎调整阈值（增加灵敏度）
                        if (mIncreasedSensitivityTiming[now_ch] >= (_TOUCH_RELEASE_INCREASED_INTERVAL / _TOUCH_REF_MAX_VALUE_LATER_TIME))
                        {
                            mIncreasedSensitivityTiming[now_ch] = (_TOUCH_RELEASE_INCREASED_INTERVAL / _TOUCH_REF_MAX_VALUE_LATER_TIME);
                            // 调整阈值
                            VALID_VALUE[now_ch] -= _TOUCH_KEY_VALID_INCREMENT;
                            if (VALID_VALUE[now_ch] < fluctuating)
                                VALID_VALUE[now_ch] = fluctuating;
                            INVALID_VALUE[now_ch] = (VALID_VALUE[now_ch] >> 1) + 1;
                            // 调低基准值（增加灵敏度）
                            if (nearby >= 2)
                                mRefValue[now_ch] -= (nearby >> 1);
                            else
                                mRefValue[now_ch] = mValidMaxValue[now_ch]; // 更新基准值
                        }
                        // 初始化
                        mValidMaxValue[now_ch] = cap_value;
                        mValidMinValue[now_ch] = cap_value;
                        mValidValueTime[now_ch] = 0;
                    }
#else
                    if (mKeyUpCont[now_ch] >= (_TOUCH_KEY_RESET_REF_INTERVAL / _TOUCH_KEY_SCAN_INTERVAL)) //松手的时间达到重置基准值
                    {
                        if (diff_value >= _TOUCH_KEY_SAFE_RESET_DIFF) // 当前值在 基准值-1 以上
                        {
                            mRefValue[now_ch] = cap_value; // 直接作为新的基准值
                            mKeyUpCont[now_ch] = 0;
                        }
                        else //当前值变小，且小了很多(-2及以下)
                        {
                            if (mKeyUpCont[now_ch] >= (_TOUCH_KEY_RESET_TIMEOUT / _TOUCH_KEY_SCAN_INTERVAL)) //达到超时时间（无条件重置时间）
                            {
                                mRefValue[now_ch] = cap_value;
                                mKeyUpCont[now_ch] = 0;
                            }
                        }
                    }
#endif
                }
            }
        }
    }
}
#endif

#ifdef _TOUCH_KEY_USE_VOLTAGE_COMPENSATE
static void VoltageCompensate()
{
    u8 now_ch;
    s16 bl;
    u16 voltage = _TouchKey_GetVDDVoltage();

    bl = (s16)((s16)mLastVDD - (s16)voltage) / _TOUCH_KEY_VOLTAGE_SENSITIVITY; //基准增加比率，千分之
    if ((bl > 3) || (bl < -3))
    {
#if (_TOUCH_KEY_CH_NUM == 1)
        mRefValue = mRefValue + ((s16)mRefValue * bl / 1000);
#else
        for (now_ch = 0; now_ch < _TOUCH_KEY_CH_NUM; now_ch++)
        {
            mRefValue[now_ch] = mRefValue[now_ch] + ((s16)mRefValue[now_ch] * bl / 1000);
        }
#endif
    }
    mLastVDD = voltage;
}
#endif
